import { RandomUtils } from "@sapi-game/utils";

export type PatternGenerator = (
    pattern: number[][],
    row: number,
    col: number
) => void;

/** 快速生成多个随机颜色池（避免频繁调用随机） */
const makePalette = (n = 4) => {
    const colors: number[] = [];
    for (let i = 0; i < n; i++) colors.push(RandomUtils.int(16));
    return colors;
};

/** 随机填充 */
const randomPattern: PatternGenerator = (pattern, row, col) => {
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            pattern[i][j] = RandomUtils.int(16);
        }
    }
};

/** 行统一颜色 */
const rowLinePattern: PatternGenerator = (pattern, row, col) => {
    for (let i = 0; i < row; i++) {
        const color = RandomUtils.int(16);
        for (let j = 0; j < col; j++) {
            pattern[i][j] = color;
        }
    }
};

/** 列统一颜色 */
const colLinePattern: PatternGenerator = (pattern, row, col) => {
    for (let i = 0; i < col; i++) {
        const color = RandomUtils.int(16);
        for (let j = 0; j < row; j++) {
            pattern[j][i] = color;
        }
    }
};

const diagonalLinePattern: PatternGenerator = (pattern, row, col) => {
    // 每条斜线唯一编号范围：[0, row + col - 2]
    const diagCount = row + col - 1;
    const colors = new Array(diagCount);

    // 为每条斜线分配一个随机颜色
    for (let d = 0; d < diagCount; d++) {
        colors[d] = RandomUtils.int(16);
    }

    // 赋值到图案中
    const direction = RandomUtils.bool();
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            if (direction) {
                // 正斜线
                pattern[i][j] = colors[i + j];
            } else {
                // 反斜线
                pattern[i][j] = colors[row - 1 - i + j];
            }
        }
    }
};

/** 多色棋盘格 */
const checkerPattern: PatternGenerator = (pattern, row, col) => {
    const palette = makePalette(16);
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            const blockX = Math.floor(i / 2);
            const blockY = Math.floor(j / 2);
            const idx = (blockX + blockY) % palette.length;
            pattern[i][j] = palette[idx];
        }
    }
};

/** 圆心渐变 */
const radialPattern: PatternGenerator = (pattern, row, col) => {
    const cx = row / 2;
    const cy = col / 2;
    const maxDist = Math.ceil(Math.sqrt(cx * cx + cy * cy));

    // 生成每一圈的随机颜色
    const circleColors = new Array(maxDist);
    for (let r = 0; r < maxDist; r++) {
        circleColors[r] = RandomUtils.int(16);
    }

    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            const dist = Math.floor(Math.sqrt((i - cx) ** 2 + (j - cy) ** 2));
            pattern[i][j] = circleColors[dist];
        }
    }
};

/** 噪声块（小范围随机重复） */
const blockNoisePattern: PatternGenerator = (pattern, row, col) => {
    const blockSize = RandomUtils.intRange(2, 5);
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            const color =
                ((Math.floor(i / blockSize) + Math.floor(j / blockSize)) * 7) %
                16;
            pattern[i][j] = color;
        }
    }
};

/** 水平波纹 */
const wavePattern: PatternGenerator = (pattern, row, col) => {
    const freq = RandomUtils.intRange(1, 5);
    const palette = makePalette(20);
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            const v = Math.sin((i / row) * Math.PI * freq) * 8;
            pattern[i][j] =
                palette[
                    (((Math.floor(v) + j) % palette.length) + palette.length) %
                        palette.length
                ];
        }
    }
};

const randomCirclesPattern: PatternGenerator = (pattern, row, col) => {
    const numCircles = RandomUtils.intRange(15, 25);
    const palette = new Array(16).fill(0).map(() => RandomUtils.int(16));

    // 初始化画布
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            pattern[i][j] = 0;
        }
    }

    for (let n = 0; n < numCircles; n++) {
        const radius = RandomUtils.intRange(2, Math.max(row, col) / 4);
        const cx = RandomUtils.int(row);
        const cy = RandomUtils.int(col);
        const color = palette[RandomUtils.int(palette.length)];
        const isRing = radius > 5 ? RandomUtils.bool() : false;
        const thickness = isRing
            ? RandomUtils.intRange(2, Math.max(1, Math.floor(radius / 2)))
            : 0;

        const radiusSq = radius * radius;
        const innerSq = isRing ? (radius - thickness) ** 2 : 0;

        for (let i = 0; i < row; i++) {
            const dx = i - cx;
            const dx2 = dx * dx;
            for (let j = 0; j < col; j++) {
                const dy = j - cy;
                const dist2 = dx2 + dy * dy;

                if (isRing) {
                    if (dist2 >= innerSq && dist2 <= radiusSq) {
                        pattern[i][j] = color;
                    }
                } else {
                    if (dist2 <= radiusSq) {
                        pattern[i][j] = color;
                    }
                }
            }
        }
    }
};

const fastNoiseCirclePattern: PatternGenerator = (pattern, row, col) => {
    const numCircles = RandomUtils.intRange(20, 30);
    const palette = makePalette(16);

    // 初始化画布为背景颜色
    const bgColor = palette[RandomUtils.int(palette.length)];
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) pattern[i][j] = bgColor;
    }

    // 网格分布圆心
    const gridRows = Math.ceil(Math.sqrt(numCircles * (row / col)));
    const gridCols = Math.ceil(numCircles / gridRows);
    const cellHeight = Math.floor(row / gridRows);
    const cellWidth = Math.floor(col / gridCols);

    let circlesPlaced = 0;
    for (let r = 0; r < gridRows && circlesPlaced < numCircles; r++) {
        for (let c = 0; c < gridCols && circlesPlaced < numCircles; c++) {
            const radius = RandomUtils.intRange(2, Math.max(row, col) / 6);
            const cx = r * cellHeight + RandomUtils.int(cellHeight);
            const cy = c * cellWidth + RandomUtils.int(cellWidth);
            const color = palette[RandomUtils.int(palette.length)];
            const radiusSq = radius * radius;

            const xStart = Math.max(0, cx - radius);
            const xEnd = Math.min(row, cx + radius + 1);
            const yStart = Math.max(0, cy - radius);
            const yEnd = Math.min(col, cy + radius + 1);

            for (let i = xStart; i < xEnd; i++) {
                const dx2 = (i - cx) * (i - cx);
                for (let j = yStart; j < yEnd; j++) {
                    const dy2 = (j - cy) * (j - cy);
                    if (dx2 + dy2 <= radiusSq) {
                        pattern[i][j] = color;
                    }
                }
            }

            circlesPlaced++;
        }
    }
};

const randomNoisePattern: PatternGenerator = (pattern, row, col) => {
    const palette = new Array(16).fill(0).map(() => RandomUtils.int(16));

    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            // 选择一个基本随机颜色
            let colorIndex = palette[RandomUtils.int(palette.length)];

            // 可选：小范围扰动，让相邻像素有些相似性但不规律
            if (i > 0 && j > 0) {
                const mix = RandomUtils.bool()
                    ? pattern[i - 1][j]
                    : pattern[i][j - 1];
                if (RandomUtils.bool()) colorIndex = mix;
            }

            pattern[i][j] = colorIndex;
        }
    }
};

const squareRingPattern: PatternGenerator = (pattern, row, col) => {
    const cx = Math.floor(row / 2);
    const cy = Math.floor(col / 2);

    // 最大层数由最短边决定
    const maxLayer = Math.ceil(Math.min(row, col) / 2);

    for (let layer = 0; layer < maxLayer; layer++) {
        // 每层生成一个随机颜色，范围根据画布大小可扩大
        const color = RandomUtils.int(16);

        // 上边
        const iTop = cx - layer;
        if (iTop >= 0) {
            const jStart = Math.max(0, cy - layer);
            const jEnd = Math.min(col, cy + layer + 1);
            for (let j = jStart; j < jEnd; j++) pattern[iTop][j] = color;
        }

        // 下边
        const iBottom = cx + layer;
        if (iBottom < row) {
            const jStart = Math.max(0, cy - layer);
            const jEnd = Math.min(col, cy + layer + 1);
            for (let j = jStart; j < jEnd; j++) pattern[iBottom][j] = color;
        }

        // 左边
        const jLeft = cy - layer;
        if (jLeft >= 0) {
            const iStart = Math.max(0, cx - layer + 1);
            const iEnd = Math.min(row, cx + layer);
            for (let i = iStart; i < iEnd; i++) pattern[i][jLeft] = color;
        }

        // 右边
        const jRight = cy + layer;
        if (jRight < col) {
            const iStart = Math.max(0, cx - layer + 1);
            const iEnd = Math.min(row, cx + layer);
            for (let i = iStart; i < iEnd; i++) pattern[i][jRight] = color;
        }
    }
};

const SquarePattern: PatternGenerator = (pattern, row, col) => {
    const numSquares = RandomUtils.intRange(30, 40); // 方形数量

    // 初始化画布为0
    const backColor = RandomUtils.int(16);
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) pattern[i][j] = backColor;
    }

    for (let s = 0; s < numSquares; s++) {
        const size = RandomUtils.intRange(
            3,
            Math.floor(Math.min(row, col) / 4)
        ); // 方形边长
        const x = RandomUtils.int(row); // 方形左上角 x
        const y = RandomUtils.int(col); // 方形左上角 y
        const color = RandomUtils.int(16);

        const xEnd = Math.min(row, x + size);
        const yEnd = Math.min(col, y + size);

        for (let i = x; i < xEnd; i++) {
            for (let j = y; j < yEnd; j++) {
                pattern[i][j] = color;
            }
        }
    }
};

export const PixelPartyPatterns = [
    randomPattern,
    rowLinePattern,
    colLinePattern,
    diagonalLinePattern,
    checkerPattern,
    radialPattern,
    blockNoisePattern,
    wavePattern,
    randomCirclesPattern,
    randomNoisePattern,
    fastNoiseCirclePattern,
    squareRingPattern,
    SquarePattern,
];
